local M = {
  "neovim/nvim-lspconfig",
  enabled = false,
  event = "VeryLazy",
  dependencies = {
    "williamboman/mason.nvim",
    "williamboman/mason-lspconfig.nvim",

    -- neovim 的lsp 语法格式错误检测
    "folke/neodev.nvim",
    -- Lsp 的相关插件加载的工作进度
    "j-hui/fidget.nvim",

    "WhoIsSethDaniel/mason-tool-installer.nvim",
  },
}

function M.config()
  -- local signs = { Error = " ", Warn = " ", Hint = "󰠠 ", Info = " " }
  -- local signs = { Error = " ", Warn = " ", Hint = " ", Info = " " }
  -- for type, icon in pairs(signs) do
  --   local hl = "DiagnosticSign" .. type
  --  -- 被弃用了 vim.fn.sign_define
  --   vim.fn.sign_define(hl, { text = icon, texthl = hl, numhl = "" })
  -- end
  local x = vim.diagnostic.severity
  vim.diagnostic.config {
    virtual_text = {
      -- source = "always",  -- Or "if_many"
      prefix = "■-> ", -- Could be '●', '■', '▎', 'x'
    },
    virtual_lines = false, --  多行诊断信息, 可以不设置, 使用插件trouble.nvim 在 buffer 中显示更加友好
    signs = {
      text = {
        -- [x.ERROR] = '',
        -- [x.WARN] = '',
        -- [x.INFO] = '',
        -- [x.HINT] = '󰌵',

        -- [x.ERROR] = '',
        -- [x.WARN] = '',
        -- [x.INFO] = '󰋇',
        -- [x.HINT] = '󰌵',

        [x.ERROR] = "✘",
        [x.WARN] = "",
        [x.HINT] = "⚑",
        [x.INFO] = "",
      },
    },
    underline = true,
    severity_sort = true,
    update_in_insert = true,
    float = {
      source = true, -- Or "if_many"
    },
  }

  -- neodev 与 fidget 必须在 lsp 配置服务之前设置
  -- lua 全局变量的识别,比如 vim 还有就是和 fidget 集成
  require("neodev").setup {
    library = {
      plugins = { "nvim-dap-ui" },
      types = true,
    },
  }
  -- fidget 必须在 lsp 配置服务之前设置
  require("fidget").setup()

  require("mason").setup {
    install_root_dir = vim.fn.stdpath "data" .. "/mason",
    ui = {
      border = "rounded",
      icons = {
        package_installed = "✓",
        package_pending = "➜",
        package_uninstalled = "✗",
      },
    },
  }

  --[[
    local registry = require "mason-registry"
    local success, package = pcall(registry.get_package, "lua-language-server")
    -- print(package.name)
    if success and not package:is_installed() then
      package:install()
    end

    local nvim_lsp = require("mason-lspconfig").get_mappings().package_to_lspconfig["lua-language-server"]
    require("lspconfig")[nvim_lsp].setup({})
  ]]

  local servers = {
    ["lua-language-server"] = {
      settings = {
        Lua = {
          diagnostics = {
            globals = { "vim" },
          },
        },
      },
    },
    pyright = {},
    ["html-lsp"] = {},
    ["css-lsp"] = {},
    ["emmet-ls"] = {},
    ["typescript-language-server"] = {},
    gopls = {
      settings = {
        gopls = {
          gofumpt = true,
          codelenses = {
            gc_details = false,
            generate = true,
            regenerate_cgo = true,
            run_govulncheck = true,
            test = true,
            tidy = true,
            upgrade_dependency = true,
            vendor = true,
          },
          hints = {
            assignVariableTypes = true,
            compositeLiteralFields = true,
            compositeLiteralTypes = true,
            constantValues = true,
            functionTypeParameters = true,
            parameterNames = true,
            rangeVariableTypes = true,
          },
          analyses = {
            fieldalignment = true,
            nilness = true,
            unusedparams = true,
            unusedwrite = true,
            useany = true,
          },
          usePlaceholders = true,
          completeUnimported = true,
          staticcheck = true,
          directoryFilters = { "-.git", "-.vscode", "-.idea", "-.vscode-test", "-node_modules", "-.nvim" },
          semanticTokens = true,
        },
      },
    },
    ["rust-analyzer"] = {
      root_dir = require("lspconfig/util").root_pattern { "Cargo.toml", ".rustfmt.toml" },
      filetypes = { "rust" },
      settings = {
        ["rust-analyzer"] = {
          -- enable clippy on save
          checkOnSave = {
            command = "clippy", -- clippy / check
            extraArgs = { "--no-deps" },
          },
          imports = {
            granularity = {
              group = "module",
            },
            prefix = "self",
          },
          cargo = {
            allFeatures = true,
            buildScripts = {
              enable = true,
            },
          },
          procMacro = {
            enable = true,
            ignored = {
              leptos_macro = {
                -- optional: --
                -- "component",
                "server",
              },
            },
          },
        },
      },
    },
  }

  local mason_registry = require "mason-registry"
  local mason_lspconfig = require "mason-lspconfig"
  local lspconfig = require "lspconfig"

  for server, config in pairs(servers) do
    local success, package = pcall(mason_registry.get_package, server)
    if success and not package:is_installed() then
      package:install()
    end

    local nvim_lsp = mason_lspconfig.get_mappings().package_to_lspconfig[server]
    --  可不配置
    -- config.capabilities = require("blink.cmp").get_lsp_capabilities()
    -- config.capabilities = require("blink.cmp").get_lsp_capabilities()
    -- -- OR
    config.capabilities = require("cmp_nvim_lsp").default_capabilities()

    lspconfig[nvim_lsp].setup(config)
  end

  -- local hover_highlight_word = function(client)
  --   -- https://neovim.io/doc/user/lsp.html
  --   -- vim.notify(client.name, vim.log.levels.INFO, {})
  --   if client.server_capabilities.documentHighlightProvider then
  --     -- 光标所在的字符词语高亮相同的单词， 可以用插件： "RRethy/vim-illuminate",
  --     vim.cmd [[
  --       augroup lsp_document_highlight
  --         autocmd! * <buffer>
  --         autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()
  --         autocmd CursorMoved <buffer> lua vim.lsp.buf.clear_references()
  --       augroup END
  --     ]]
  --   end
  -- end
  --
  -- local toggle_inlay_hint = function(client, buf)
  --   -- 这样就禁止了 lsp 服务的格式操作
  --   -- client.server_capabilities.documentFormattingProvider = false
  --   -- client.server_capabilities.documentRangeFormattingProvider = false
  --   if vim.lsp.inlay_hint and client.server_capabilities.inlayHintProvider then
  --     vim.keymap.set("n", "<Space>ht", function()
  --       vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled())
  --       vim.lsp.inlay_hint.enable(vim.lsp.inlay_hint.is_enabled(), { bufnr = buf })
  --     end, { desc = "Toggle Inlay Hints." })
  --   else
  --     vim.notify "Not supported inlay hint"
  --   end
  -- end
  --
  -- local on_attach = function(buf)
  --   vim.api.nvim_buf_set_option(buf, "omnifunc", "v:lua.vim.lsp.omnifunc")
  --   local nmap = function(keys, func, desc)
  --     -- See `:help vim.lsp.*` for documentation on any of the below functions
  --     if desc then
  --       desc = "LSP: " .. desc
  --     end
  --
  --     local bufopts = {
  --       buffer = buf,
  --       desc = desc,
  --       noremap = true,
  --       silent = true,
  --     }
  --     vim.keymap.set("n", keys, func, bufopts)
  --   end
  --
  --   nmap("gD", vim.lsp.buf.declaration, "[G]oto [D]eclaration")
  --   -- rename
  --   nmap("<leader>rn", "<cmd>lua vim.lsp.buf.rename()<CR>")
  --   -- code action
  --   nmap("<space>ca", "<cmd>lua vim.lsp.buf.code_action()<CR>")
  --   -- go xx
  --   nmap("gd", "<cmd>lua vim.lsp.buf.definition()<CR>")
  --   nmap("gh", "<cmd>lua vim.lsp.buf.hover()<CR>")
  --   nmap("gD", "<cmd>lua vim.lsp.buf.declaration()<CR>")
  --   nmap("gi", "<cmd>lua vim.lsp.buf.implementation()<CR>")
  --   nmap("gr", "<cmd>lua vim.lsp.buf.references()<CR>")
  --   -- diagnostic
  --   nmap("go", "<cmd>lua vim.diagnostic.open_float()<CR>")
  --   nmap("gp", "<cmd>lua vim.diagnostic.goto_prev()<CR>")
  --   nmap("gn", "<cmd>lua vim.diagnostic.goto_next()<CR>")
  --   -- nmap('<leader>q', '<cmd>lua vim.diagnostic.setloclist()<CR>')
  --   -- leader + =
  --   nmap("<leader>=", "<cmd>lua vim.lsp.buf.formatting()<CR>")
  --   -- nmap('<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>')
  --   -- nmap('<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>')
  --   -- nmap('<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>')
  --   -- nmap('<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>')
  --   -- nmap('<space>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>')
  -- end
  --
  -- local clone = function(opts1, opts2)
  --   return vim.tbl_deep_extend("force", opts1, opts2)
  -- end
  -- local formatting = function(client, buf)
  --   local bufopts = {
  --     noremap = true,
  --     silent = true,
  --     buffer = buf,
  --     desc = "xxx",
  --   }
  --
  --   local fmt = function()
  --     require("conform").format {
  --       bufnr = buf,
  --       async = false,
  --       lsp_fallback = true, -- conform.nvim 如果不支持就用 Lsp 的格式化
  --       timeout_ms = 500,
  --     }
  --   end
  --
  --   -- 插件 conform.nvim 格式化
  --   vim.keymap.set({ "n", "v" }, "<leader>tc", function()
  --     fmt()
  --   end, clone(bufopts, { desc = "conform.nvim: [F]ormat code" }))
  --   -- 快捷键格式化
  --   vim.keymap.set({ "n", "v" }, "<leader>ls", function()
  --     --  注意这里 async = true
  --     vim.lsp.buf.format { async = true }
  --     -- fmt()
  --   end, clone(bufopts, { desc = "LSP: [F]ormat code" }))
  --
  --   if client.server_capabilities.documentFormattingProvider then
  --     -- 保存格式化
  --     vim.api.nvim_create_autocmd("BufWritePre", {
  --       group = vim.api.nvim_create_augroup("LspFormatting", { clear = true }),
  --       buffer = bufopts.buffer,
  --       callback = function()
  --         -- 注意这里 async = false,否则会不断有问题
  --         -- vim.lsp.buf.format { async = false }
  --         fmt()
  --       end,
  --     })
  --   end
  -- end

  -- vim.api.nvim_create_autocmd("LspAttach", {
  --   group = vim.api.nvim_create_augroup("UserLspConfig", {}),
  --   callback = function(ev)
  --     -- 获取服务信息
  --     local client = vim.lsp.get_client_by_id(ev.data.client_id)
  --     -- print("server name: " .. client.name)
  --     if client == nil then
  --       return
  --     end
  --
  --     on_attach(ev.buf)
  --
  --     if client.supports_method "textDocument/formatting" then
  --       -- 调用格式化的, 相关配置
  --       formatting(client, ev.buf)
  --     else
  --       vim.notify "Not supports formatting..."
  --     end
  --
  --     -- 切换是否显示 hint
  --     toggle_inlay_hint(client, ev.buf)
  --     -- 高亮鼠标悬浮的相关的所有词语, 注意代码位置顺序
  --     hover_highlight_word(client)
  --   end,
  -- })

  mason_lspconfig.setup {
    -- list of servers for mason to install
    ensure_installed = {
      "ts_ls",
      "html",
      "cssls",
      "tailwindcss",
      "svelte",
      "lua_ls",
      "graphql",
      "emmet_ls",
      "prismals",
      "pyright",
      "rust_analyzer",
    },
  }

  local mason_tool_installer = require "mason-tool-installer"
  mason_tool_installer.setup {
    ensure_installed = {
      "prettier", -- prettier formatter
      "stylua", -- lua formatter
      "isort", -- python formatter
      "black", -- python formatter
      "pylint", -- python linter
      "eslint_d", -- js linter
    },
  }

  -- mason_lspconfig.setup({
  -- 	automatic_installation = true,
  -- 	ensure_installed = {
  -- 		-- https://github.com/williamboman/mason-lspconfig.nvim
  -- 		-- https://mason-registry.dev/registry/list
  -- 		-- 使用服务器别名
  -- 		"lua_ls",
  -- 		"rust_analyzer",
  -- 		"denols",
  -- 		"ts_ls", -- typescript
  -- 		"eslint",
  -- 		"clangd",
  -- 		"denols",
  -- 		"cssls", -- SCSS
  -- 		"html",
  -- 		"tailwindcss",
  -- 		"svelte",
  -- 		"graphql",
  -- 		"emmet_ls",
  -- 		"pyright",
  -- 	},
  -- })
  --
  -- local format_servers = {
  -- 	"codelldb",
  -- 	"clang-format", -- c/c++
  -- 	"gofumpt", -- go
  -- 	"goimports", -- go
  -- 	"stylua", -- lua
  -- 	"luacheck",
  -- 	"jq", -- json
  -- 	"shfmt", -- sh
  --
  -- 	"pylint", -- python
  -- 	"black", -- python
  -- 	"isort", -- python
  -- 	"mypy", -- python
  -- 	"ruff", -- python
  -- 	"pyright",
  --
  -- 	-- "biome", -- 速度比 prettier 快的格式化工具
  -- 	"prettier", -- js
  -- 	"prettierd", -- js
  -- 	"eslint_d", -- js ts
  -- 	"markdownlint",
  -- }
  --
  -- local format_severs = function()
  -- 	for _, name in pairs(format_servers) do
  -- 		if not mason_registry.is_installed(name) then
  -- 			local package = mason_registry.get_package(name)
  -- 			vim.notify("[mason-registry]" .. " Installing " .. name)
  -- 			package:install()
  -- 		end
  -- 	end
  -- end
  -- mason_registry.refresh(vim.schedule_wrap(format_severs))
end

return M
